package initialize

import (
	"fmt"
	rotatelogs "github.com/lestrrat/go-file-rotatelogs"
	"github.com/vueadmin/utils"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"io"
	"time"
)

func GetLogClient() *zap.SugaredLogger {
	Logger, _ := getInitLogger()
	defer Logger.Sync()
	return Logger
}

func GetAccessLogClient() *zap.SugaredLogger {
	Logger, _ := GetInitAccessLogger("runtime/logs/access", "access", "log")
	defer Logger.Sync()
	return Logger
}

//get logger
func getInitLogger() (*zap.SugaredLogger, error) {
	encoder := getEncoder()
	//warnlevel以下属于info
	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl < zapcore.WarnLevel && lvl != zapcore.DebugLevel
	})
	//warnlevel及以上属于warn
	warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.WarnLevel
	})

	debugLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl == zapcore.DebugLevel
	})

	utils.CreateDir("runtime/logs/info")
	infoWriter, err := getLogWriter("runtime/logs/info/info", "log")
	if err != nil {
		return nil, err
	}

	utils.CreateDir("runtime/logs/sql")
	debugWriter, err := getLogWriter("runtime/logs/sql/sql", "log")
	if err != nil {
		return nil, err
	}

	utils.CreateDir("runtime/logs/warn")
	warnWriter, err2 := getLogWriter("runtime/logs/warn/warn", "log")
	if err2 != nil {
		return nil, err2
	}
	//创建具体的Logger
	core := zapcore.NewTee(
		zapcore.NewCore(encoder, infoWriter, infoLevel),
		zapcore.NewCore(encoder, warnWriter, warnLevel),
		zapcore.NewCore(encoder, debugWriter, debugLevel),
	)
	loggerres := zap.New(core, zap.AddCaller())

	return loggerres.Sugar(), nil
}

//get logger
func GetInitAccessLogger(filepath, filename, fileext string) (*zap.SugaredLogger, error) {
	utils.CreateDir(filepath)
	warnWriter, err2 := getLogWriter(filepath+"/"+filename, fileext)
	if err2 != nil {
		return nil, err2
	}

	var cfg zap.Config
	cfg = zap.Config{
		Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
		Development: true,
		Encoding:    "console",
		EncoderConfig: zapcore.EncoderConfig{
			MessageKey: "msg",
		},
	}

	l, err := cfg.Build(SetOutput(warnWriter, cfg))
	if err != nil {
		fmt.Println(err)
	}

	return l.Sugar(), nil
}

func SetOutput(ws zapcore.WriteSyncer, conf zap.Config) zap.Option {
	var enc zapcore.Encoder
	switch conf.Encoding {
	case "json":
		enc = zapcore.NewJSONEncoder(conf.EncoderConfig)
	case "console":
		enc = zapcore.NewConsoleEncoder(conf.EncoderConfig)
	default:
		fmt.Println("unknown encoding")
	}
	return zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		return zapcore.NewCore(enc, ws, conf.Level)
	})
}

//Encoder
func getEncoder() zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	return zapcore.NewConsoleEncoder(encoderConfig)
}

//LogWriter
func getLogWriter(filePath, fileext string) (zapcore.WriteSyncer, error) {
	warnIoWriter, err := getWriter(filePath, fileext)
	if err != nil {
		return nil, err
	}
	return zapcore.AddSync(warnIoWriter), nil
}

//日志文件切割，按天
func getWriter(filename, fileext string) (io.Writer, error) {
	// 保存30天内的日志，每24小时(整点)分割一次日志
	hook, err := rotatelogs.New(
		filename+"_%Y%m%d."+fileext,
		rotatelogs.WithLinkName(filename),
		rotatelogs.WithMaxAge(time.Hour*24*30),
		rotatelogs.WithRotationTime(time.Hour*24),
	)
	if err != nil {
		//panic(err)
		return nil, err
	}
	return hook, nil
}
